﻿using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Common;
using RotovapPlatform.Domain.Equipment.Device.Robot.Dto;
using RotovapPlatform.Domain.Equipment.Device.Robot.Enums;
using RotovapPlatform.Domain.Equipment.Interfaces.Communication;
using RotovapPlatform.Domain.Equipment.Interfaces.CPG;
using RotovapPlatform.Domain.Equipment.Interfaces.Robot;
using RotovapPlatform.Domain.Equipment.PackML;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RotovapPlatform.Infrastructure.Equipment.Devices.Robot
{
	public class RobotDrive : IRobotEM
	{
		private readonly IModbusTcpClient _modbus;
		private readonly RobotConfig _config;
		private readonly ILogger<RobotDrive> _logger;
		private PackMLState _currentState = PackMLState.Undefined;
		private PackMLMode _currentMode = PackMLMode.Auto;
		private RobotTaskSendDto _currentTask;
		private DateTime _lastReconnectAttempt = DateTime.MinValue;
		private TimeSpan _reconnectInterval = TimeSpan.FromSeconds(5); // 重连间隔5秒

		public RobotDrive(
			IModbusTcpClient modbus,
			RobotConfig config,
			ILogger<RobotDrive> logger)
		{
			_modbus = modbus;
			_config = config;
			_logger = logger;
		}

		public string Name => "Robot";
		public string EquipmentId => "Robot_1";
		public PackMLState CurrentState => _currentState;
		public PackMLMode CurrentMode => _currentMode;

		public event EventHandler<PackMLState> StateChanged;
		public event EventHandler<PackMLMode> ModeChanged;

		public async Task<(RobotTaskFeedBackDto TaskFeedback, RobotStatusDto DeviceStatus)> GetStatusAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
				{
					// 尝试重连
					await TryReconnectAsync();

					_logger.LogWarning("机器人已断开连接，尝试返回断开状态");
					return (new RobotTaskFeedBackDto
					{
						RobotProcessState = RobotProcessState.Disconnected
					}, new RobotStatusDto());
				}

				var taskFeedback = await ReadTaskFeedbackAsync();
				var deviceStatus = await ReadDeviceStatusAsync();

				return (taskFeedback, deviceStatus);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "读取机器人状态失败");
				return (new RobotTaskFeedBackDto
				{
					RobotProcessState = RobotProcessState.Disconnected
				}, new RobotStatusDto());
			}
		}

		/// <summary>
		/// 尝试重新连接Modbus
		/// </summary>
		private async Task TryReconnectAsync()
		{
			// 控制重连频率，避免频繁重连
			if (DateTime.Now - _lastReconnectAttempt < _reconnectInterval)
			{
				return;
			}

			_lastReconnectAttempt = DateTime.Now;
			_logger.LogInformation("尝试重新连接机器人...");

			try
			{
				// 如果已连接，先断开
				if (_modbus.IsConnected)
				{
					await _modbus.DisconnectAsync();
				}

				// 尝试重新连接
				await _modbus.ConnectAsync();

				if (_modbus.IsConnected)
				{
					_logger.LogInformation("机器人重连成功");
				}
				else
				{
					_logger.LogWarning("机器人重连尝试失败");
				}
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人重连失败");
			}
		}

		private async Task<RobotStatusDto> ReadDeviceStatusAsync()
		{
			var statusBits = await _modbus.ReadDiscreteInputsAsync(
				_config.SlaveId,
				_config.DeviceStatusStartAddress,
				11);

			return new RobotStatusDto
			{
				IsIdle = statusBits[0],
				IsProgramPaused = statusBits[1],
				IsProgramRunning = statusBits[2],
				IsError = statusBits[3],
				IsPoweredOn = statusBits[4],
				IsEnabled = statusBits[5],
				IsMoving = statusBits[6],
				IsStopped = statusBits[7],
				IsMachineOn = statusBits[8],
				IsEmergencyStopped = statusBits[9],
				IsProtectiveStopped = statusBits[10]
			};
		}

		private async Task<RobotTaskFeedBackDto> ReadTaskFeedbackAsync()
		{
			var registers = await _modbus.ReadInputRegistersAsync(
				_config.SlaveId,
				_config.TaskFeedbackStartAddress,
				6);

			return new RobotTaskFeedBackDto
			{
				RobotProcessState = (RobotProcessState)registers[0],
				RobotTaskFinishState = registers[1],
				RobotGripperState = (InstallState)registers[2],
				RobotArrivedSignal_1 = registers[3],
				RobotArrivedSignal_2 = registers[4],
				RobotArrivedSignal_3 = registers[5]
			};
		}

		public async Task<OperationResult> StartAsync(ushort start)
		{
			try
			{
				if (_modbus.Master == null)
				{
					_logger.LogError("Modbus主站未初始化");
					return OperationResult.Fail("Modbus主站未初始化");
				}

				// 发送启动信号
				var startSignal = new RobotTaskStartDto { Start = start };
				var result = await WriteTaskStartAsync(startSignal);

				if (!result)
				{
					return OperationResult.Fail("机器人启动失败");
				}


				_currentState = PackMLState.Execute;
				StateChanged?.Invoke(this, _currentState);
				return OperationResult.Ok("机器人启动成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "启动任务失败");
				return OperationResult.Fail($"启动任务失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SetTaskParametersAsync(RobotTaskSendDto task)
		{
			try
			{
				_currentTask = task ?? throw new ArgumentNullException(nameof(task));
				// 立即发送任务参数到机器人
				var result = await WriteTaskAsync(_currentTask);
				if (!result.Success)
					return OperationResult.Fail(result.Message);

				return OperationResult.Ok("设置任务参数成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置任务参数失败");
				return OperationResult.Fail($"设置任务参数失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SendControlCommandAsync(RobotControlCommandDto command)
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 先发送控制命令
				var result = await WriteControlCommandAsync(command);
				if (!result)
					return OperationResult.Fail("发送控制命令失败");

				// 等待指定时间
				await Task.Delay(TimeSpan.FromSeconds(1));

				// 清除所有控制命令
				var clearCommand = new RobotControlCommandDto();
				var clearResult = await WriteControlCommandAsync(clearCommand);

				if (!clearResult)
					return OperationResult.Fail("清除控制命令失败");

				return OperationResult.Ok("控制命令执行成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "发送控制命令失败");
				return OperationResult.Fail($"发送控制命令失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> HandleProcessSignalsAsync(RobotProcessSignalsDto processSignals)
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 写入继续执行信号
				var continueExecutionSignal = new ushort[]
				{ processSignals.WaitingPoint1Confirm,
				processSignals.WaitingPoint2Confirm,
				processSignals.WaitingPoint3Confirm };

				var result = await _modbus.WriteMultipleRegistersAsync(
					_config.SlaveId,
					_config.ContinueExecutionSignalAddress,
					continueExecutionSignal);

				return result ? OperationResult.Ok("过程信号处理成功") : OperationResult.Fail("过程信号处理失败");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "处理过程信号失败");
				return OperationResult.Fail($"处理过程信号失败: {ex.Message}");
			}
		}

		private async Task<OperationResult> WriteTaskAsync(RobotTaskSendDto task)
		{
			try
			{
				var taskRegisters = new ushort[]
				{
				(ushort)task.TaskType,
				task.BottleType,
				task.Position,
				task.NeedScan
				};

				var result = await _modbus.WriteMultipleRegistersAsync(
					_config.SlaveId,
					_config.TaskSendStartAddress,
					taskRegisters);

				return result ? OperationResult.Ok("写入机器人任务成功") : OperationResult.Fail("写入机器人任务失败");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "写入机器人任务失败");
				return OperationResult.Fail($"写入机器人任务失败: {ex.Message}");
			}
		}

		private async Task<bool> WriteTaskStartAsync(RobotTaskStartDto startSignal)
		{
			try
			{
				var startRegister = new ushort[] { startSignal.Start };
				return await _modbus.WriteMultipleRegistersAsync(
					_config.SlaveId,
					_config.TaskStartAddress,
					startRegister);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "写入任务启动信号失败");
				return false;
			}
		}

		private async Task<bool> WriteControlCommandAsync(RobotControlCommandDto command)
		{
			try
			{
				var controlBits = new[]
				{
				command.StartProgram,
				command.PauseProgram,
				command.ContinueProgram,
				command.PowerOn,
				command.PowerOff,
				command.Enable,
				command.Disable,
				command.ProtectiveStop,
				command.ClearError,
				command.PowerOnSystem,
				command.PowerOffSystem,
				command.RobotUp,
				command.RobotDown
			};

				return await _modbus.WriteMultipleCoilsAsync(
					_config.SlaveId,
					_config.ControlCommandStartAddress,
					controlBits);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "写入机器人控制命令失败");
				return false;
			}
		}

		public async Task<OperationResult> InitializeAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现初始化逻辑
				return OperationResult.Ok("机器人初始化成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人初始化失败");
				return OperationResult.Fail($"机器人初始化失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> StopAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现停止逻辑
				return OperationResult.Ok("机器人停止成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人停止失败");
				return OperationResult.Fail($"机器人停止失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> AbortAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现中止逻辑
				return OperationResult.Ok("机器人中止成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人中止失败");
				return OperationResult.Fail($"机器人中止失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> ClearAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现清除逻辑
				return OperationResult.Ok("机器人清除成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人清除失败");
				return OperationResult.Fail($"机器人清除失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> ResetAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现重置逻辑
				return OperationResult.Ok("机器人重置成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人重置失败");
				return OperationResult.Fail($"机器人重置失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SuspendAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现暂停逻辑
				return OperationResult.Ok("机器人暂停成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人暂停失败");
				return OperationResult.Fail($"机器人暂停失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> UnsuspendAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现恢复逻辑
				return OperationResult.Ok("机器人恢复成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人恢复失败");
				return OperationResult.Fail($"机器人恢复失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> HoldAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现保持逻辑
				return OperationResult.Ok("机器人保持成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人保持失败");
				return OperationResult.Fail($"机器人保持失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> UnHoldAsync()
		{
			try
			{
				if (!_modbus.IsConnected)
					return OperationResult.Fail("机器人未连接");

				// 实现解除保持逻辑
				return OperationResult.Ok("机器人解除保持成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "机器人解除保持失败");
				return OperationResult.Fail($"机器人解除保持失败: {ex.Message}");
			}
		}

		Task<bool> IUnitMachine.InitializeAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.StartAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.StopAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.AbortAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.ClearAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.ResetAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.SuspendAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.UnsuspendAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.HoldAsync()
		{
			throw new NotImplementedException();
		}

		Task<bool> IUnitMachine.UnHoldAsync()
		{
			throw new NotImplementedException();
		}

		// ... 实现其他IRobotEM接口方法
	}
}
